package com.shanzmoo.core.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.shanzmoo.base.bean.SResponse;
import com.shanzmoo.base.constant.Constant;
import com.shanzmoo.base.constant.PayStatusConstant;
import com.shanzmoo.base.constant.e.WxTradeTypeEnum;
import com.shanzmoo.core.config.pay.MyWxPayConfig;
import com.shanzmoo.core.service.ICommonPayService;
import com.shanzmoo.db.order.entity.bo.PayMoneyResultBO;
import com.shanzmoo.db.trade.entity.PayOrderEntity;
import com.shanzmoo.core.domain.pay.PayOrderEntityLocalUtil;
import com.shanzmoo.core.domain.pay.WxPayOrderDto;
import com.shanzmoo.core.domain.pay.PayResultResp;
import com.shanzmoo.core.pay.sdk.wxpay.WXPay;
import com.shanzmoo.core.pay.sdk.wxpay.WXPayConstants;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信，支付实现类
 *
 * @author: Gzhao 2020/12/9
 */
@Slf4j
public class WxCommonPayServiceImpl implements ICommonPayService {
    /**
     * 回调地址
     */
    private String notifyUrl;

    public WxCommonPayServiceImpl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }

    @Override
    public SResponse<String> tradeQrCode() {
        try {
            WxPayOrderDto wxPayOrderDto = WxPayOrderDto.create(PayOrderEntityLocalUtil.getPayOrderEntity());
            MyWxPayConfig config = new MyWxPayConfig();
            WXPay wxpay = new WXPay(config);

            Map<String, String> resp = wxpay.unifiedOrder(wxPayOrderDto.convertMap(notifyUrl));

            if (WXPayConstants.SUCCESS.equals(resp.get("result_code"))) {
                PayOrderEntityLocalUtil.setOrderStatus(true);
                return SResponse.ok(resp.get("code_url"));

            } else {
                PayOrderEntityLocalUtil.setOrderStatus(false);
                return SResponse.fail(Constant.ERRCODE_LOGIC, "微信支付下单失败: " + resp.get("return_msg"));
            }
        } catch (Exception e) {
            log.error("微信下单，生成二维码失败", e);
            PayOrderEntityLocalUtil.setOrderStatus(false);

            return SResponse.fail(Constant.ERRCODE_LOGIC, "微信支付下单失败：" + e.getMessage());
        }
    }

    @Override
    public SResponse<PayMoneyResultBO> tradePay(String authCode) {
        try {
            PayOrderEntity payOrderEntity = PayOrderEntityLocalUtil.getPayOrderEntity();
            payOrderEntity.setTradeType(WxTradeTypeEnum.MICROPAY.getDesc());

            WxPayOrderDto wxPayOrderDto = WxPayOrderDto.createByAuthCode(payOrderEntity, authCode);

            MyWxPayConfig config = new MyWxPayConfig();
            WXPay wxpay = new WXPay(config);

            Map<String, String> resp = wxpay.microPay(wxPayOrderDto.convertMap());

            PayMoneyResultBO resultBO = new PayMoneyResultBO();
            if (!WXPayConstants.SUCCESS.equals(resp.get("return_code"))){

                resultBO.setOrderSuccess(false);
                resultBO.setPaySuccess(false);
                resultBO.setMessage("微信扫码支付下单失败");

                log.error("微信扫码支付下单失败, {}", resp);
                return SResponse.ok(resultBO);
            }

            log.debug("微信扫码支付下单成功");
            resultBO.setOrderSuccess(true);
            resultBO.setPayNo(payOrderEntity.getPayNo());

            if (WXPayConstants.SUCCESS.equals(resp.get("result_code"))) {
                payOrderEntity.setFinishTime(LocalDateTimeUtil.parse(resp.get("time_end"), "yyyyMMddHHmmss"));
                payOrderEntity.setPayStatus(PayStatusConstant.PAY_SUCCESS);

                resultBO.setPaySuccess(true);
                resultBO.setMessage("支付成功");

                return SResponse.ok(resultBO);
            }

            log.info("微信扫码支付下单成功, 等待支付");

            // 等待用户支付密码
            if ("USERPAYING".equals(resp.get("err_code"))) {

                log.info("微信扫码支付下单成功, 等待用户支付密码");
                resultBO.setPaySuccess(false);
                resultBO.setMessage("微信扫码支付下单成功, 等待用户支付密码");

                return SResponse.ok(resultBO);

            }

            String errMsg = StrUtil.isNotBlank(resp.get("err_code_des")) ? resp.get("err_code_des") : resp.get("return_msg");

            log.error("微信扫码支付失败，{}", errMsg);
            return SResponse.fail(Constant.ERRCODE_LOGIC, "微信扫码支付失败: " + errMsg);

        } catch (Exception e) {
            log.error("微信扫码支付失败：", e);

            return SResponse.fail(Constant.ERRCODE_LOGIC, "微信扫码支付失败：" + e.getMessage());
        }
    }

    @Override
    public SResponse<PayResultResp> queryPayResult(String payNo) {
        try {
            MyWxPayConfig config = new MyWxPayConfig();
            WXPay wxpay = new WXPay(config);

            Map<String, String> data = new HashMap<>();
            data.put("out_trade_no", payNo);
            Map<String, String> resp = wxpay.orderQuery(data);

            PayOrderEntity payOrder = PayOrderEntityLocalUtil.getPayOrderEntity();
            PayOrderEntityLocalUtil.setQueryRespBody(JSON.toJSONString(resp));
            if (WXPayConstants.SUCCESS.equals(resp.get("result_code"))) {
                /*
                    SUCCESS—支付成功
                    REFUND—转入退款
                    NOTPAY—未支付
                    CLOSED—已关闭
                    REVOKED—已撤销（付款码支付）
                    USERPAYING--用户支付中（付款码支付）
                    PAYERROR--支付失败(其他原因，如银行返回失败)
                 */
                if ("SUCCESS".equals(resp.get("trade_state"))) {
                    // 支付成功
                    payOrder.setFinishTime(LocalDateTimeUtil.parse(resp.get("time_end"), "yyyyMMddHHmmss"));
                    payOrder.setPayStatus(PayStatusConstant.PAY_SUCCESS);

                    return SResponse.ok(PayResultResp.createSuccess());

                }
                // 已关闭 ||  已撤销（付款码支付）
                else if ("CLOSED".equals(resp.get("trade_state")) || "REVOKED".equals(resp.get("trade_state"))
                        || "PAYERROR".equals(resp.get("trade_state"))) {
                    payOrder.setPayStatus(PayStatusConstant.PAY_Fail);

                    return SResponse.ok(PayResultResp.createFail(resp.get("trade_state_desc")));
                } else {

                    return SResponse.ok(PayResultResp.createFail(resp.get("trade_state_desc")));
                }

            } else {
                // 微信未获取到正确的数据
                return SResponse.ok(PayResultResp.createFail("微信支付订单查询失败：" + resp.get("err_code_des")));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信支付订单查询失败：" + e.getMessage());
            return SResponse.fail(Constant.ERRCODE_LOGIC, "微信支付订单查询失败：" + e.getMessage());
        }

    }
}
